using System;
using System.Web.Security;
using System.Web.UI.WebControls;
using System.Text.RegularExpressions;
using Oplaco.Core.BusinessLogicLayer;
using Oplaco.Web.UI;
using Oplaco.Core.Configuration;
using System.Web;
using System.Configuration;
using System.Linq;
using LinqToTwitter;


/// <summary>
/// Credits to LinqToTwitter
/// </summary>
/// <see cref="http://linqtotwitter.codeplex.com/"/>
public partial class Register_aspx : System.Web.UI.Page
{
    private const string OAuthCredentialsKey = "OAuthCredentialsKey";
    private SignInAuthorizer auth;
    private TwitterContext twitterCtx;
    private Uri callbackUri = new Uri(ConfigurationManager.AppSettings["TwitterCallbackUrl"]);

    protected void Page_Load(object sender, EventArgs e)
    {
        InfoLabel.Visible = false;
        //set page title for SEO
        Oplaco.Core.Configuration.SiteSettings settings = Oplaco.Core.Configuration.SiteSettings.GetSharedSettings();
        Page.Title = settings.SiteName + " | " + SiteMap.CurrentNode == null ? SiteMap.CurrentNode.Title : String.Empty;


        //twitter handling
        #region Twitter integration
        IOAuthCredentials credentials = new InMemoryCredentials();
        string authString = Session[OAuthCredentialsKey] as string;

        if (authString == null)
        {
            credentials.ConsumerKey = ConfigurationManager.AppSettings["twitterConsumerKey"];
            credentials.ConsumerSecret = ConfigurationManager.AppSettings["twitterConsumerSecret"];

            Session[OAuthCredentialsKey] = credentials.ToString();
        }
        else
        {
            credentials.Load(authString);
        }

        auth = new SignInAuthorizer
        {
            Credentials = new InMemoryCredentials
            {
                ConsumerKey = ConfigurationManager.AppSettings["twitterConsumerKey"],
                ConsumerSecret = ConfigurationManager.AppSettings["twitterConsumerSecret"]
            },
            PerformRedirect = authUrl => Response.Redirect(authUrl)
        };

        if (!Page.IsPostBack)
        {
            if (!string.IsNullOrEmpty(credentials.ConsumerKey) && !string.IsNullOrEmpty(credentials.ConsumerSecret))
            {
                if (auth.CompleteAuthorization(Request.Url))
                {
                    LinqToTwitter.User usr = (from twUsr in twitterCtx.User where twUsr.ScreenName == auth.ScreenName select twUsr).SingleOrDefault<LinqToTwitter.User>();

                    //now as we are working with twitter, we do not know a password. So we generate one, in order to have fallback
                    
                    this.registerUser(auth.ScreenName, Password.Text, Nickname.Text, PhoneNumberPrefix.Text, PhoneNumber.Text, PostalCode.Text, PostalCodeExtension.Text);
                }
            }
        
        }
        #endregion
    }


    
    protected void Page_Error(object sender, EventArgs e)
    {
        Response.Redirect("~/Error.aspx");
    }


    /// <summary>
    /// Twitter registration
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void btnSubmitTwitterLogin_Click(object sender, EventArgs e) {

        callbackUri = new Uri(@"http://localhost:49866/Oplaco_example_site/Register.aspx"); //for debuggin
        auth.BeginAuthorization(callbackUri, forceLogin: true);
        
        
    }

    /// <summary>
    /// Creates the user in the databases
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void btnSubmit_CreateUser(object sender, EventArgs e)
    {
        if (Page.IsValid)
        {

            this.registerUser(Email.Text, Password.Text, Nickname.Text, PhoneNumberPrefix.Text, PhoneNumber.Text, PostalCode.Text, PostalCodeExtension.Text);

            //todo: insert mail functionality here

            //todo: automatically login the user?
            Server.Transfer("~/Login.aspx");

        }
    }



    private void registerUser(string email, string password, string nickname, string phoneNrPrefix, string phoneNr, string zipcode, string zipcodeExt) {


        MembersDB MDB = new MembersDB();
        try
        {
            MDB.CreateUser(email, password);
            MDB.UpdateProfile(email, nickname, String.Empty, String.Empty, phoneNrPrefix, phoneNr, Int32.Parse(zipcode), zipcodeExt, String.Empty, String.Empty, String.Empty, String.Empty, string.Empty, string.Empty);
                       
        }
        catch (Oplaco.Exceptions.BusinessLayerException BLE)
        {
            CustomValidator val = new CustomValidator();
            val.IsValid = false;
            val.ErrorMessage = ConfigurationManager.AppSettings["GenericErrorMessage"];
            val.ValidationGroup = "RegisterGroup";
            this.Page.Validators.Add(val);
            Oplaco.Exceptions.AppService.ProcessAndNotifyPresentationLayerException(BLE);
        }
        catch (MembershipCreateUserException MCUE)
        {
            this.handleCreateUserError(MCUE);
        }
        catch (Exception exception)
        {
            CustomValidator val = new CustomValidator();
            val.IsValid = false;
            val.ErrorMessage = ConfigurationManager.AppSettings["GenericErrorMessage"];
            val.ValidationGroup = "RegisterGroup";
            this.Page.Validators.Add(val);
            Oplaco.Exceptions.AppService.ProcessAndNotifyPresentationLayerException(exception);
        }
    }
     


    /// <summary>
    /// handleCreateUserError : handles localization of errors caused by MembershipCreateUserException
    /// </summary>
    /// <param name="e">MembershipCreateUserException</param>
    private void handleCreateUserError(MembershipCreateUserException e)
    {
        CustomValidator val = new CustomValidator();
        val.IsValid = false;
        val.ValidationGroup = "RegisterGroup";
        
        System.Text.StringBuilder mailLink = new System.Text.StringBuilder(this.GetMailLink());
        try
        {
            switch (e.StatusCode)
            {
                case MembershipCreateStatus.DuplicateUserName:
                    val.ErrorMessage = GetLocalResourceObject("InfoLabelDuplicatieUserName.Text").ToString();
                    break;

                case MembershipCreateStatus.DuplicateEmail:
                    val.ErrorMessage = GetLocalResourceObject("InfoLabelDuplicatieEmail.Text").ToString();
                    break;

                case MembershipCreateStatus.InvalidPassword:
                    val.ErrorMessage = GetLocalResourceObject("InfoLabelInvalidPassword.Text").ToString();
                    break;

                case MembershipCreateStatus.InvalidEmail:
                    val.ErrorMessage = GetLocalResourceObject("InfoLabelInvalidEmail.Text").ToString();
                    break;

                case MembershipCreateStatus.ProviderError:
                    val.ErrorMessage = GetLocalResourceObject("InfoLabelProviderError.Text").ToString() + mailLink.ToString() + ".";
                    break;

                case MembershipCreateStatus.UserRejected:
                    val.ErrorMessage = GetLocalResourceObject("InfoLabelUserRejected.Text").ToString() + mailLink.ToString() + ".";
                    break;

                default:
                    val.ErrorMessage = ConfigurationManager.AppSettings["GenericErrorMessage"].ToString() + mailLink.ToString() + "."; 
                    break;
            }
        }
        //failsafe
        catch (Exception exception) {
            
            switch (e.StatusCode)
            {
                case MembershipCreateStatus.DuplicateUserName:
                    val.ErrorMessage = "A user name for that e-mail address already exists. Please enter a different username.";
                    break;

                case MembershipCreateStatus.DuplicateEmail:
                    val.ErrorMessage = "A user name for that e-mail address already exists. Please enter a different e-mail address.";                    
                    break;

                case MembershipCreateStatus.InvalidPassword:
                    val.ErrorMessage = "The password provided is invalid. " +
                        "Please enter a valid password . " +
                        "Acceptable passwords are at least 7 characters long and contain at least 1 non-alphanumeric character.";
                    break;

                case MembershipCreateStatus.InvalidEmail:
                    val.ErrorMessage = "The e-mail address provided is invalid. Please check the value and try again.";
                    break;


                case MembershipCreateStatus.ProviderError:
                    val.ErrorMessage = "The authentication provider returned an error. " +
                        "Please verify your entry and try again. " +
                        "If the problem persists, please contact the " +
                        mailLink.ToString() + ".";
                    break;

                case MembershipCreateStatus.UserRejected:
                    val.ErrorMessage = "The user creation request has been canceled. " +
                        "Please verify your entry and try again. " +
                        "If the problem persists, please contact the " +
                        mailLink.ToString() + ".";
                    break;

                default:
                    val.ErrorMessage = "An unknown error occurred. " +
                        "Please verify your entry and try again. " +
                        "If the problem persists, please contact the " +
                        mailLink.ToString() + ".";
                    break;
            }
        }

        this.Page.Validators.Add(val);
    }

    
    private String GetMailLink()
    {
        System.Text.StringBuilder mailLink = new System.Text.StringBuilder("<a href=\"mailto:");
        try
        {
            mailLink.Append(SiteSettings.GetSharedSettings().SiteEmailAddress);
        }
        catch
        {
            mailLink.Append("#");
        }
        mailLink.Append("\">system administrator</a>");
        return mailLink.ToString();
    }

    
}
